package com.alcohol.auth.server.support.grant.password;

import com.alcohol.auth.server.constant.CommonConstants;
import com.alcohol.auth.server.support.grant.base.BaseAuthenticationConverter;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 密码认证转换器
 * @author LiXinYu
 * @date 2025/11/8
 */
public class PasswordAuthenticationConverter extends BaseAuthenticationConverter<PasswordAuthenticationToken> {

    /**
     * 校验参数
     * @param parameters 请求入参
     */
    @Override
    public void checkParams(MultiValueMap<String, String> parameters) {
        // username (REQUIRED)
        String username = parameters.getFirst(OAuth2ParameterNames.USERNAME);
        if (!StringUtils.hasText(username) || parameters.get(OAuth2ParameterNames.USERNAME).size() != 1) {
            throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, "用户名不能为空！", null));
        }

        // password (REQUIRED)
        String password = parameters.getFirst(OAuth2ParameterNames.PASSWORD);
        if (!StringUtils.hasText(password) || parameters.get(OAuth2ParameterNames.PASSWORD).size() != 1) {
            throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR, "密码不能为空！", null));
        }
    }


    /**
     * 构建具体类型的token
     * @param parameters 请求入参
     * @param clientPrincipal 客户端认证信息
     * @param requestedScopes 请求的认证作用域
     * @param additionalParameters 扩展信息
     * @return 认证令牌
     */
    @Override
    public PasswordAuthenticationToken buildToken(MultiValueMap<String, String> parameters, Authentication clientPrincipal, Set<String> requestedScopes, Map<String, Object> additionalParameters) {
        String username = parameters.getFirst(OAuth2ParameterNames.USERNAME);
        String password = parameters.getFirst(OAuth2ParameterNames.PASSWORD);
        return new PasswordAuthenticationToken(username, password, clientPrincipal, requestedScopes, additionalParameters);
    }

    /**
     * 获取附加信息
     * @param parameters 请求入参
     * @return 附加信息
     */
    @Override
    public Map<String, Object> getAdditionalParameters(MultiValueMap<String, String> parameters) {
        return parameters.entrySet().stream()
                .filter(e -> !e.getKey().equals(OAuth2ParameterNames.GRANT_TYPE) && !e.getKey().equals(OAuth2ParameterNames.SCOPE)
                        && !e.getKey().equals(CommonConstants.USERNAME) && !e.getKey().equals(CommonConstants.PASSWORD))
                .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getFirst()));
    }
}
